package com.young.pattern.prototypePattern;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * 原型模式
 */
@Slf4j
public class client {


    /***
     * 原型模式:使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象;
     *  结构:
     *      1,prototype(抽象原型类):是声明克隆方法的接口,是所有具体原型类的公共父类,可以是抽象类也可以是接口,甚至可以是具体实现类
     *      2,concretePrototype(具体原型类):实现在抽象原型类中声明的克隆方法,在克隆方法中返回自己的一个克隆对象.
     *      3,client(客户类):在客户类中,让一个原型对象克隆自身从而创建一个新的对象,只需要直接实例化或通过工厂方法等方式创建一个原型对象,
     *          再通过调用该对象的克隆方法即可得到多个相同的对象.由于客户类针对抽象原型类Prototype编程,因此用户可以根据需要选择具体原型类,
     *          系统具有教好的可扩展性,增加或更换具体原型类都很方便
     *
     * 优点:
     *  1,当创建新的对象实例较为复杂时,使用原型模式可以可以简化对象的创建过程,通过复制一个已有实例可以提高新实例的创建效率;
     *  2,扩展性较好,由于在原型模式中提供了抽象原型类,在客户端可以针对抽象原型类进行编程,而将具体原型类写在配置文件中,增加或减少产品类对原有系统没有任何影响
     *  3,原型模式提供了简化的创建结构,工厂方法模式常常需要有一个与产品类等级结构相同的工厂等级结构,而原型模式就不需要这样,原型模式中产品的产品的复制是通过封装在
     *      原型类中的克隆方法实现的,无需专门的工厂类来创建产品
     *  4,可以使用深克隆的方式保存对象的状态,使用原型模型将对象复制一份并将其状态保存起来,以便在需要的时候使用,可辅助实现撤销操作.
     * 缺点:
     *  1,需要为每一个类配置一个克隆方法,而且该克隆方法位于一个类的内部,当对已有的类进行改造时需要修改源代码,违背了开闭原则;
     *  2,在实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重的嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来可能比较麻烦.
     *
     */
    public static void main(String[] args) {
        Attachment attachment = new Attachment();
        attachment.setName("我是附件");
        WeeklyLog firstWeek = new WeeklyLog();
        firstWeek.setAttachment(attachment);
        WeeklyLog secondWeek = firstWeek.deepClone();
        //  比较值的大小
        log.info("复制后附件地址值是否相同:{}",firstWeek.getAttachment().equals(secondWeek.getAttachment()));
        log.info("复制后周报地址值是否相同:{}",firstWeek.equals(secondWeek));
        log.info("周报1:{}",firstWeek );
        log.info("周报2:{}",secondWeek );
        //  比较引用是否相同
        log.info("复制后附件引用是否相同:{}",firstWeek.getAttachment()== secondWeek.getAttachment());
        log.info("复制后周报引用是否相同:{}",firstWeek==secondWeek);

    }

}
